package com.biz.primus.ms.coupon.event.listener;

import com.biz.primus.ms.base.jpa.po.BaseEntity;
import com.biz.primus.ms.coupon.dao.po.CouponType;
import com.biz.primus.ms.coupon.dao.redis.CouponRedisDao;
import com.biz.primus.ms.coupon.dao.redis.CouponTypeRedisDao;
import com.biz.primus.ms.coupon.dao.ro.CouponRo;
import com.biz.primus.ms.coupon.dao.ro.CouponTypeRo;
import com.biz.primus.ms.coupon.event.couponType.*;
import com.biz.primus.ms.coupon.service.CouponTypeService;
import com.biz.primus.ms.coupon.trans.CouponType2CouponTypeRo;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;

/**
 * 优惠券类型时间监听器
 *
 * @author david-liu
 */
@Component
@Slf4j
public class CouponTypeEventListener {

    @Autowired
    private CouponTypeRedisDao couponTypeRedisDao;

    @Autowired
    private CouponRedisDao couponRedisDao;

    @Autowired
    private CouponTypeService couponTypeService;

    @TransactionalEventListener
    public void handleCreateCouponTypeEvent(CreateCouponTypeEvent event) {
        CouponType couponType = event.getCouponType();
        if (Objects.isNull(couponType)) {
            log.warn("coupon type is null");
        } else {
            Long couponTypeId = couponType.getId();
            CouponTypeRo couponTypeRo = new CouponType2CouponTypeRo().apply(couponType);
            couponTypeRedisDao.save(couponTypeRo);
            if (couponTypeRo.isPreBuildCoupon()) {
                List<CouponRo> couponRos = couponTypeService.generateToBeFetchedCoupons(couponTypeId, couponType.getTotalQuantity());
                couponRedisDao.save(couponRos);
                couponRedisDao.appendCouponType2BeFetchedCoupons(couponTypeId, couponRos.stream().map(CouponRo::getId).collect(Collectors.toList()));
            }
        }
    }

    @TransactionalEventListener
    public void handleUpdateCouponTypeEvent(UpdateCouponTypeEvent event) {
        CouponType couponType = event.getCouponType();
        if (Objects.isNull(couponType)) {
            log.warn("coupon type is null");
        } else {
            Long couponTypeId = couponType.getId();
            CouponTypeRo couponTypeRo;
            if (couponTypeRedisDao.isExists(couponTypeId)) {
                couponTypeRo = couponTypeRedisDao.findOne(couponTypeId);
                couponTypeRo.setBrands(CollectionUtils.isEmpty(couponType.getBrands()) ? "" : StringUtils.join(couponType.getBrands(), ","));
                couponTypeRo.setCategories(CollectionUtils.isEmpty(couponType.getCategories()) ? "" : StringUtils.join(couponType.getCategories(), ","));
                couponTypeRo.setIncludeProducts(CollectionUtils.isEmpty(couponType.getIncludeProducts()) ? "" : StringUtils.join(couponType.getIncludeProducts(), ","));
                couponTypeRo.setExcludeProducts(CollectionUtils.isEmpty(couponType.getExcludeProducts()) ? "" : StringUtils.join(couponType.getExcludeProducts(), ","));
                couponTypeRo.setVendors(CollectionUtils.isEmpty(couponType.getVendors()) ? "" : StringUtils.join(couponType.getVendors(), ","));
                couponTypeRo.setCouponLimitAmount(couponType.getCouponLimitAmount());
                couponTypeRo.setFaceValue(couponType.getFaceValue());
                couponTypeRo.setCouponLimitType(couponType.getCouponLimitType());
                couponTypeRo.setCouponTypeName(couponType.getCouponTypeName());
                couponTypeRo.setCouponScopeType(couponType.getCouponScopeType());
                couponTypeRo.setCreator(couponType.getCreator());
                couponTypeRo.setLastUpdateUser(couponType.getLastUpdateUser());
                couponTypeRo.setEnable(couponType.getEnable());
                couponTypeRo.setReceivableEndTime(couponType.getReceivableEndTime());
                couponTypeRo.setReceivableStartTime(couponType.getReceivableStartTime());
                couponTypeRo.setUsableStartTime(couponType.getUsableStartTime());
                couponTypeRo.setUsableEndTime(couponType.getUsableEndTime());
                couponTypeRo.setIcon(couponType.getIcon());
                couponTypeRo.setRemark(couponType.getRemark());
                couponTypeRo.setUsableCountDownDays(couponType.getUsableCountDownDays());
            } else {
                couponTypeRo = new CouponType2CouponTypeRo().apply(couponType);
            }
            couponTypeRedisDao.save(couponTypeRo);
        }
    }

    @TransactionalEventListener
    public void handleUpdateCouponTypeInfoEvent(UpdateCouponTypeInfoEvent event) {
        CouponType couponType = event.getCouponType();
        if (Objects.isNull(couponType)) {
            log.warn("coupon type is null");
        } else {
            Long couponTypeId = couponType.getId();
            if (couponTypeRedisDao.isExists(couponTypeId)) {
                CouponTypeRo couponTypeRo = couponTypeRedisDao.findOne(couponTypeId);
                couponTypeRo.setIcon(couponType.getIcon());
                couponTypeRo.setCouponTypeName(couponType.getCouponTypeName());
                couponTypeRo.setCouponTypeDesc(couponType.getCouponTypeDesc());
                couponTypeRo.setRemark(couponType.getRemark());
                couponTypeRo.setLastUpdateUser(couponType.getLastUpdateUser());
                couponTypeRedisDao.save(couponTypeRo);
            }
        }
    }

    @TransactionalEventListener
    public void handleUpdateCouponTypeStatusEvent(UpdateCouponTypeStatusEvent event) {
        List<CouponType> couponTypes = event.getCouponTypeList();
        Boolean status = event.getStatus();
        if (CollectionUtils.isNotEmpty(couponTypes)) {
            List<Long> couponTypeIds = couponTypes.stream().map(BaseEntity::getId).collect(Collectors.toList());
            List<CouponTypeRo> couponTypeRos = couponTypeRedisDao.findByIds(couponTypeIds);
            couponTypeRos.forEach(couponTypeRo -> couponTypeRo.setEnable(status));
            couponTypeRedisDao.save(couponTypeRos);
        }
    }

    @TransactionalEventListener
    public void handleAppendCouponTypeIssueCountEvent(AppendCouponTypeIssuedCountEvent event) {
        CouponTypeRo couponTypeRo = event.getCouponTypeRo();
        Integer appendCount = event.getAppendIssueCount();
        Long couponTypeId = couponTypeRo.getId();
        if (couponTypeRo.isPreBuildCoupon()) {
            List<CouponRo> couponRos = couponTypeService.generateToBeFetchedCoupons(couponTypeId, appendCount);
            couponRedisDao.save(couponRos);
            couponRedisDao.appendCouponType2BeFetchedCoupons(couponTypeId, couponRos.stream().map(CouponRo::getId).collect(Collectors.toList()));
        }
    }
}
